
#pragma once

#include <memory>
#include <string>
#include <vector>

#include "abstract_expression.h"
#include "catalog.hpp"
#include "logical_type.hpp"

namespace DaseX {
/**
 * ColumnValueExpression maintains the tuple index and column index relative to
 * a particular schema or join.
 */
class ColumnValueExpression : public AbstractExpression {
public:
  /**
   * ColumnValueExpression is an abstraction around "Table.member" in terms of
   * indexes.
   * @param tuple_idx {tuple index 0 = left side of join, tuple index 1 = right
   * side of join}
   * @param col_idx the index of the column in the schema
   * @param ret_type the return type of the expression
   */
  ColumnValueExpression(uint32_t tuple_idx, uint32_t col_idx,
                        LogicalType ret_type)
      : AbstractExpression({}, ret_type), tuple_idx_{tuple_idx},
        col_idx_{col_idx} {}

  auto Evaluate(const arrow::RecordBatch *tuple,
                const arrow::Schema &schema) const -> int override {
    return col_idx_;
    // return tuple->GetValue(&schema, col_idx_);
  }

  auto EvaluateJoin(const arrow::RecordBatch *left_tuple,
                    const arrow::Schema &left_schema,
                    const arrow::RecordBatch *right_tuple,
                    const arrow::Schema &right_schema) const -> int override {

    return tuple_idx_ == 0 ? col_idx_ : col_idx_;
  }

  auto GetTupleIdx() const -> uint32_t { return tuple_idx_; }
  auto GetColIdx() const -> uint32_t { return col_idx_; }

  EXPR_CLONE_WITH_CHILDREN(ColumnValueExpression);

private:
  /** left side is 0, right side is 1 */
  uint32_t tuple_idx_;
  /** column index in the output_schema, used in translate between operators,
   * e.g. schema {A,B,C} has indexes {0,1,2} */
  uint32_t col_idx_;
};
} // namespace DaseX
